home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 9
/
Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO
/
050a
/
bfmt139.zip
/
BFMT.CPP
next >
Wrap
C/C++ Source or Header
|
1993-04-28
|
22KB
|
760 lines
/*
want to edit stdin and output stdout
output either justified or left aligned or right aligned
centered or adjusted (c++ mode)
user specified width (of character field only), inherit
word spacing, all lines as paragraphs, specify spacing etc
bfmt -fl -w40
plan :
get line of input and next (flag if no more)
if new para reset whitespace
else separate into words and spaces
pass words and spaces to format type
format type :
arrange words and spaces
output to cout
history :
1.33 bug in editing paragraph with ^Z on last line
13/4/93 fixed in version 1.34
15/4/93 fixed bug that deleted words if paragraph too big
in version 1.37
18/4/93 make last line in justified paragraph unfmt. (1.38)
27/4/93 tried to convert to SunOS c++ ,re suggestion Yan Xu
28/4/93 tested, done and improved by Yan Xu
slight modifications by me (1.39)
to fix error in max_words_per_line
*/
// --------------------------------------------------------------
#include <time.h>
#include <ctype.h>
#include <iostream.h>
#include <fstream.h>
#include <iomanip.h>
#include <stdlib.h>
#include <string.h>
#define VERSION "1.39"
#define MAX_LINE_LEN 160
#define MAX_NUM_WORDS 80
#define MAX_WORD_SZ 80
#define WNUM_OFFSET 30
#define MIN_WIDTH 10
#define MAX_SP 80
// ------------------------------------ struct typedefs
typedef struct {
char searchkey[20];
char format[3];
char pmarkers[10];
char smarkers[10];
int min;
int paraspace;
int keep;
int text;
int inherit;
int allpara;
int width;
} frmt;
frmt Fmt = {
"@#$%^Blb)8",
// searchkey
"l",
// left aligned
"./",
// para markers
".?!*",
// sentence markers
4,
// minimum number of words to format justify
8,
// paragraph spacing
1,
// keep text directed formatting info
1,
// obey text directed formatting
1,
// space inherited
0,
// all lines as paragraphs
72 };
// width
typedef struct {
char space[ MAX_LINE_LEN ];
char param[ MAX_LINE_LEN];
int lspace;
int wnum;
int restspace;
char words [MAX_NUM_WORDS] [MAX_WORD_SZ];
int newp;
int oldallpara;
int oldinherit;
int end;
} wdinfo;
wdinfo Words = {
"",
"",
0,
0,
0,
"",
1,
0,
1,
0 } ;
char buffer [MAX_LINE_LEN] = "";
// --------------------------------------------------------------
int PUsage(void) {
cout << "\nText formatting version " << VERSION << endl;
cout << "send donations to Brendan Babb \n";
cout << " @ microbiol dept,";
cout << " Univ. Ave, UCT, Rondebosch 7700, RSA\n";
cout <<
"\nUSAGE: BFMT [options listed below]\n"
" [<{input}] [>{output}] where input and output are filenames\n"
" [-f{type}] types are l,r,j,c,u,a\n"
" [-i{0|1}] inherit whitespace [-s{width}] whitespace width\n"
" [-a{0|1}] all lines are paragraphs\n"
" [-t{0|1}] obey options in text \n"
" [-k{0|1}] keep options in text\n"
" [-({sentence delimiters}] [-{{paragraph delimiters}]\n"
" [-w{width}] right margin\n"
" [-m{min}] minimum words to justify\n"
" [/u] save previous options to default\n"
" [?|-h|-?] display this and current defaults\n";
return 0;
}
// --------------------------------------------------------------
int PValues() {
cout << "\nCurrent default values :\n";
cout << setw(28) << "sentence markers " << setw(6)
<< Fmt.smarkers;
cout << setw(28) << "paragraph markers " << setw(6)
<< Fmt.pmarkers << endl;
cout << setw(28) << "paragraph spacing " << setw(6)
<< Fmt.paraspace;
cout << setw(28) << "all lines as para " << setw(6)
<< Fmt.allpara << endl;
cout << setw(28) << "keep param lines " << setw(6) << Fmt.keep;
cout << setw(28) << "obey param lines " << setw(6)
<< Fmt.text << endl;
cout << setw(28) << "format " << setw(6) << Fmt.format;
cout << setw(28) << "whitespace inhertited " << setw(6)
<< Fmt.inherit << endl;
cout << setw(28) << "width " << setw(6) << Fmt.width;
cout << setw(28) << "minimum words to fmt " << setw(6)
<< Fmt.min << endl;
return 0;
}
// ----------------------------------- work horses
/*
divide must divide the input buffer into as many words as it
can handle, until no more input, or until max words
or only one line if allpara
returning 1 prevents more input
its function is to set up global variables Word and buffer for
the work to be done
if new para, must quit, the format functions
will then organize the words and spaces as need be
to check for new para must look at string of paramarkers
and pass any info they may contain to the format function.
format sub_functions must return number words used so can
update info in words.
update_words must return how many words left.
will continue formating if any words left or
still input information
*/
// ----------------------------------------------------- now do work
int divide () {
char temp [MAX_LINE_LEN];
// stores space in case needed
for (unsigned int ch,i=0; isspace(ch = buffer[i]); i++) {
if (ch == '\n'|| ch == '\0') {
Words.newp = 1;
buffer[0] = '\0'; // ie just space
return 1; // 1 means stop adding
}
temp[i] = ch;
}
if (ch == EOF) {
Words.end =1; // must prevent
// more input
Words.newp = 0;
buffer[0] = '\0';
return 1;
}
if (buffer[strlen(buffer)-1] == '\n')
buffer[strlen(buffer)-1] = '\0';
if (strchr(Fmt.pmarkers,ch)) { // check if para marker
strcpy(Words.param, &buffer[i]);
ch = strlen(Words.param);
if (Words.param[ch-1] == '\n')
Words.param[ch-1] = '\0';
buffer[0] = '\0';
Words.newp = 1;
return 1;
}
temp[i] = '\0'; // make sure space
// is terminated
if (Words.newp || Fmt.allpara) strcpy(Words.space, temp);
// -------------------------------- extract words
int w_ctr; // internal word counter
// Words.wnum = #words
// j is position marker
for (int j=i; j < strlen(buffer); j++) {
w_ctr = 0;
if (buffer[j] == EOF) {
Words.end = 1;
break;
}
if (isspace(buffer[j])) continue;
// ignore space
while (!isspace(ch=buffer[j])) {
Words.words [Words.wnum][w_ctr] = ch;
j++;
w_ctr++;
}
// one complete word fnd
Words.words [Words.wnum] [w_ctr] = '\0';
// check if is a sentence
if (strchr(Fmt.smarkers,buffer[j-1])) {
Words.words [Words.wnum] [w_ctr] = ' ';
Words.words [Words.wnum] [w_ctr+1] = '\0';
}
if (strlen(Words.words[Words.wnum])) Words.wnum++;
if (buffer[j] == '\0' )
break;
if (buffer[j] == EOF) {
Words.end = 1;
break; }
}
Words.newp = 0;
strcpy(temp, &buffer[i]);
strcpy(buffer,temp);
if (Fmt.allpara) return 1;
if (Words.wnum >= (MAX_NUM_WORDS) - (WNUM_OFFSET))
return 1;
return Words.newp;
}
// ------------------------------------------- space calc
// assumes tab = 8
int Calc_space_len() {
int pos = 0;
for (int i=0, s_ptr = 0; i < strlen(Words.space) ; i++) {
if (Words.space[s_ptr] == '\t')
pos = pos | 7;
else Words.space[s_ptr] = ' ';
pos++;
}
Words.lspace = pos;
return 0;
}
// --------------------------------------- update words list
int update_words(int nwords) { // nword = words used
char temp [MAX_WORD_SZ];
for (int num = nwords ; num < Words.wnum ; num++) {
strcpy(temp, Words.words[num]);
strcpy(Words.words[num - nwords], temp);
}
Words.wnum = Words.wnum - nwords ;
if (Words.wnum < 0) Words.wnum = 0;
return 0;
}
// ------------------------------------------------- MAX words
int Max_words_wid(int stnum) {
int num = 0;
int width;
if (Fmt.inherit) width = Words.lspace;
else width = Fmt.paraspace;
for (int i=stnum; i< Words.wnum; i++) {
if ((width + strlen(Words.words[i])) < Fmt.width) {
width += 1 + strlen(Words.words[i]);
num++;
}
else
break;
}
return (num);
}
// ------------------------------------------- format setup
int Fmt_setup() {
Words.oldallpara = Fmt.allpara;
Words.oldinherit = Fmt.inherit;
if (!strcmp(Fmt.format,"a")) {
Fmt.allpara = 1;
Fmt.inherit = 0;
Words.restspace = 0;
}
if (!strcmp(Fmt.format,"u")) {
Fmt.allpara = 1;
Fmt.inherit = 1;
}
if (Fmt.width < (MIN_WIDTH)) Fmt.width = MIN_WIDTH +1;
return 0;
}
//------------------------------------------------- format output
int fmt_out(char *b, int ws = -1) {
char temp[MAX_SP];
if (cin.eof()) Words.end = 1;
for (int i = 0; i< MAX_SP; i++)
temp[i] = ' ';
if (ws == -1) {
if (!Fmt.inherit) temp[Fmt.paraspace] = '\0';
else strcpy(temp, Words.space);
}
else {
if (ws>=0&&ws<80) temp[ws] = '\0';
else ws = Fmt.paraspace;
}
if (b&&Words.wnum) {
cout << temp << b << endl;
}
return 0;
}
// ------------------------------------------ print parameters
int fmt_prm() {
if (Fmt.keep) {
cout << Words.param;
}
if (!Words.end)
if (Words.newp) cout << endl;
return 0;
}
// ------------------------------------------- left fmt
int fmt_left () {
int wnum = 0;
int nword;
do {
nword = Max_words_wid(wnum);
strcpy(buffer,"");
for (int i= 0; i < nword; wnum++, i++) {
strcat(buffer, Words.words[wnum]);
strcat(buffer, " \0");
}
buffer[strlen(buffer)-1] = '\0';
if (nword == 0 && Words.wnum) {
strcpy(buffer, Words.words[wnum]);
wnum++;
}
fmt_out(buffer);
if (Words.wnum - wnum<1) break;
} while ( Words.newp ||
Words.wnum - wnum >= WNUM_OFFSET || Words.end) ;
fmt_prm();
return (wnum);
}
//------------------------------------------------- unchanged fmt
int fmt_unchanged() {
int i = strlen(buffer)-1;
if (buffer[i] == '\n')
buffer[i] = '\0';
fmt_out(buffer);
fmt_prm();
return (Words.wnum);
}
//------------------------------------------------- right fmt
int fmt_right () {
int nword, space, wnum = 0;
do {
nword = Max_words_wid(wnum);
buffer[0] = '\0';
for (int i= 0; i < nword; wnum++, i++) {
strcat(buffer, Words.words[wnum]);
strcat(buffer, " ");
}
space = strlen(buffer)-1;
buffer[space] = '\0';
if (buffer[space-1] == ' ') {
buffer[space-1] = '\0';
space--; }
if (nword == 0 && Words.wnum) {
strcpy(buffer, Words.words[wnum]);
wnum++;
}
fmt_out(buffer,Fmt.width-space);
if (Words.wnum - wnum<1) break;
} while ( Words.newp || Words.wnum - wnum >= WNUM_OFFSET) ;
fmt_prm();
return (wnum);
}
//------------------------------------------------- adjust fmt
// this needs each line to be dealt seperately
// set up fmt so that allpara = 1, space =0 - not inherited;
// also uses Words.restspace to keep track of where is.
int fmt_adjust() {
int space = Fmt.paraspace + Words.restspace;
if (Words.words[0][0] == '#'||Words.words[0][0] == '/')
space = 0;
if (space <0) space = 0;
if (buffer[strlen(buffer)-1] == '\n')
buffer[strlen(buffer)-1] = '\0';
fmt_out(buffer, space);
if (strchr(buffer,'{'))
Words.restspace += 8;
if (strchr(buffer,'}'))
Words.restspace -= 8;
if (Words.restspace <0) Words.restspace = 0;
fmt_prm();
return (Words.wnum);
}
//------------------------------------------------- centre fmt
int fmt_centre () {
int wnum, nword, cw;
nword = cw =wnum = 0;
do {
nword = Max_words_wid(wnum);
buffer[0] = '\0';
for (int i= 0; i < nword; wnum++, i++) {
strcat(buffer, Words.words[wnum]);
strcat(buffer, " ");
}
buffer[strlen(buffer)-1] = '\0';
if (Fmt.inherit) cw = - Words.lspace;
else cw = - Fmt.paraspace;
cw += Fmt.width - strlen(buffer);
cw /= 2;
if (Fmt.inherit) cw += Words.lspace;
else cw += Fmt.paraspace;
if (nword == 0 && Words.wnum) {
strcpy(buffer, Words.words[wnum]);
wnum++;
}
fmt_out(buffer, cw);
if (Words.wnum - wnum<1) break;
} while ( Words.newp || Words.wnum - wnum >= WNUM_OFFSET) ;
fmt_prm();
return (wnum);
}
//------------------------------------------------- justify text
int fmt_just () {
int wnum, nword, cw, wc, offset, rnum;
nword = cw =wnum = wc = offset = 0;
char spaces [WNUM_OFFSET] [MAX_LINE_LEN];
time_t t;
srand((unsigned) time(&t));
do {
buffer[0] = '\0';
nword = Max_words_wid(wnum);
cw = 0;
if (Words.newp && nword+wnum == Words.wnum)
{
for (int i= 0; i < nword; wnum++, i++) {
strcat(buffer, Words.words[wnum]);
strcat(buffer, " ");
}
buffer[strlen(buffer)-1] = '\0';
}
else if (nword >= Fmt.min) {
for (int i=0; i < nword; i++) {
wc = wnum + i;
strcpy(spaces[i], " ");
cw += strlen(Words.words[wc]) + 1;
}
if (Fmt.inherit) offset = - Words.lspace;
else offset = - Fmt.paraspace;
offset += Fmt.width - cw + 1;
// if last word is end sentence
if ((strchr(Words.words[wc],' '))) {
offset++;
cw = strlen(Words.words[wc])-1;
Words.words[wc] [cw] = '\0';
}
for (i=0; i < offset; i++) {
rnum = rand() % (nword-1);
strcat(spaces[rnum]," ");
}
spaces[nword-1][0] = '\0';
for (i=0; i < nword; wnum++, i++) {
strcat(buffer,Words.words[wnum]);
strcat(buffer,spaces[i]);
}
}
else
{
for (int i= 0; i < nword; wnum++, i++) {
strcat(buffer, Words.words[wnum]);
strcat(buffer, " ");
}
buffer[strlen(buffer)-1] = '\0';
}
if (nword == 0 && Words.wnum) {
strcpy(buffer, Words.words[wnum]);
wnum++;
}
fmt_out(buffer);
if (Words.wnum - wnum<1) break;
} while ( Words.newp || Words.wnum - wnum >= WNUM_OFFSET) ;
fmt_prm();
return (wnum);
}
//------------------------------------------------- interpret paraline
int parameter_intr() {
char *p;
if (Words.param) {
if (Fmt.text) {
if (p = strstr(Words.param, "-a")) {
Fmt.allpara = p[2] - '0';
Words.oldallpara = Fmt.allpara;
}
if (p = strstr(Words.param, "-f")) {
Fmt.format[0] = p[2];
if (Fmt.format[0] == 'a'||Fmt.format[0] == 'u') {
Fmt.allpara = 1;
Fmt.inherit = 0;
if (Fmt.format[0] == 'u') Fmt.inherit = 1;
}
else {
Fmt.allpara = Words.oldallpara;
Fmt.inherit = Words.oldinherit;
}
}
if (p = strstr(Words.param, "-i"))
Fmt.inherit = p[2] - '0';
if (p = strstr(Words.param, "-k"))
Fmt.keep = p[2] - '0';
if (p = strstr(Words.param, "-s"))
Fmt.paraspace = atoi(&p[2]);
if (strstr(Words.param, "-h"))
PValues();
if (p = strstr(Words.param, "-w")) {
Fmt.width = atoi(&p[2]);
if (Fmt.width < (MIN_WIDTH)) Fmt.width = MIN_WIDTH +1;
}
}
}
return 0;
}
// ------------------------------------- save configuration
int Config(char *p) { // note no error checking
fstream file;
#ifdef MSDOS
file.open(p, ios::in|ios::binary|ios::out);
#else
file.open(p, ios::in|ios::out);
#endif
long f_ptr = 0;
int c_ptr = 0;
unsigned char ch,cb;
if (!file) {
cout << "could not open file (" << p;
cout << ") to configure\n";
return 1;
}
while (file.get(ch)) {
f_ptr++;
cb = Fmt.searchkey[c_ptr];
if (ch == cb) c_ptr++;
else c_ptr = 0;
if (cb == 0) break ;
}
f_ptr -= strlen(Fmt.searchkey)+1;
file.seekp(f_ptr, ios::beg);
file.write(Fmt.searchkey,sizeof(frmt));
file.close();
return 0;
}
// --------------------------------------------------------------
int main(int argc,char *argv[])
{
char Pswitch;
char *Val;
char *Name;
Name = argv[0];
if (argc > 1) for (argv++ ; *argv; argv++) {
char *thisArg = *argv;
if (*thisArg != '-' && *thisArg != '/') {
PUsage();
PValues();
return 0; }
Pswitch = *(thisArg+1);
Val = thisArg+2;
switch (Pswitch) {
case 'a' : Fmt.allpara = atoi(Val);
break ;
case '?' :
case 'h' : PUsage();
PValues() ;
return 0;
case 'v' : cout << "\nBrendan's format program";
cout << " version " << VERSION;
cout << endl;
return 0;
case 'm' : Fmt.min = atoi(Val);
break ;
case 'f' : strcpy(Fmt.format,Val);
break ;
case 'w' : Fmt.width = atoi(Val);
break ;
case 'i' : Fmt.inherit = atoi(Val);
break ;
case 't' : Fmt.text = atoi(Val);
break ;
case 'k' : Fmt.keep = atoi(Val);
break ;
case 's' : Fmt.paraspace = atoi(Val);
break ;
case 'u' : Config(Name);
break;
case '{' : strcpy(Fmt.pmarkers, Val);
break ;
case '(' : strcpy(Fmt.smarkers, Val);
break ;
}
}
// ----------------------------------- main loop
int nwords, endinput, wd_fin;
Words.newp = 1;
Words.restspace = 0;
Fmt_setup();
do {
endinput = nwords = 0;
do {
if (cin.eof()) {
Words.end = 1;
break ;
}
cin.getline(buffer, MAX_LINE_LEN);
endinput += divide();
if (Fmt.allpara) break;
} while (!(endinput)) ;
Calc_space_len();
switch (Fmt.format[0]) {
case 'l' : nwords = fmt_left();
break;
case 'r' : nwords = fmt_right();
break;
case 'j' : nwords = fmt_just();
break;
case 'c' : nwords = fmt_centre();
break;
case 'a' : nwords = fmt_adjust();
break;
case 'u' : nwords = fmt_unchanged();
break;
}
wd_fin = update_words(nwords);
parameter_intr();
// allows text specified formatting
buffer[0] = '\0';
Words.param[0] = '\0';
} while (!wd_fin&&!Words.end);
// ----------------------------------- finish and close
return 0;
}
// -------------------------------------------------------- END